iT邦幫忙

2024 iThome 鐵人賽

DAY 15
2
Python

從概念到應用:Python實戰開發學習之旅系列 第 15

[Day14] 第二週 - 進階工程師的開端 - 提升python效能、品質、維護的小技巧

  • 分享至 

  • xImage
  •  

今日目標

各位~辛苦了
到了今天進階工程師之路也即將到尾聲
今天本來是要講解虛擬環境、log、錯誤處理三個

但我想要可以幫大家可以提升技能的小技巧就盡量補足

  1. 虛擬環境
  2. log使用
  3. 錯誤處理的應用
  4. python推導
  5. 效能運算-迴圈及向量比較

Skill-1 避免開發環境汙染 - 虛擬環境

定義

項目 內容
定義 Python 虛擬環境是一個獨立的 Python 環境,包含特定版本的 Python 解釋器及其相關庫。
好處 1. 隔離性:每個虛擬環境都是獨立的,避免依賴衝突。
2. 控制依賴性:可為每個項目指定特定版本的庫,確保一致性和可重現性。
3. 無需管理員權限:安裝包不需要管理員權限,適合共享或限制權限的環境。
4. 便於打包和分享:輕鬆導出和共享虛擬環境的依賴列表。
5. 支持多個 Python 版本:可為不同項目創建使用不同 Python 版本的虛擬環境。

其實在許多程式語言開發也有類似的方式來做環境隔離或是使用docker容器化的技術
不過這變不提XDD/images/emoticon/emoticon01.gif
想學習的大大可以到devops專欄找大神看看技術文章

優點 缺點
減少衝突:降低因版本不兼容而導致的錯誤。 管理複雜性:需要額外步驟來創建和管理虛擬環境。
提高可維護性:清晰地管理每個項目的依賴,使更新和維護變得簡單。 資源消耗:每個虛擬環境佔用一定磁碟空間,許多虛擬環境可能導致存儲資源浪費。
促進協作:團隊成員可使用相同虛擬環境配置,確保代碼一致性。 切換成本:在多個虛擬環境之間切換時,需要手動激活和停用,影響工作流。

指令表

編號 指令 功能 使用場景
1 python -m venv <directory> 創建一個新的虛擬環境 當需要為一個新項目創建隔離的開發環境時。
2 source <directory>/bin/activate 啟動虛擬環境(Linux/MacOS) 在 Linux 或 MacOS 上啟動虛擬環境。
3 <directory>\Scripts\activate 啟動虛擬環境(Windows) 在 Windows 上啟動虛擬環境。
4 deactivate 停用當前的虛擬環境 當完成工作後退出虛擬環境時使用。
5 python -m pip install <package> 在虛擬環境中安裝指定的包 在虛擬環境中安裝所需的第三方庫或依賴。
6 pip list 列出當前虛擬環境中安裝的所有包 檢查虛擬環境中的依賴和版本。
7 pip freeze > requirements.txt 將當前虛擬環境中的包及其版本輸出到文件 當需要共享或重建虛擬環境時使用。
8 pip install -r requirements.txt 根據文件中的列表安裝所有依賴 從文件中批量安裝所需的依賴包。

示範

這邊會以
1.創建
2.進入環境
3.停用

三項來demo
1.創建python -m venv webdevelop(創建網頁開發環境)

https://ithelp.ithome.com.tw/upload/images/20240929/20121052cDnnzWGBcD.png

tips - 使用這個指令會在當前目錄下建立資料夾目錄,這個例子就是會建立webdevelop

  1. 啟動環境 webdeveop\Scripts\activate.bat

https://ithelp.ithome.com.tw/upload/images/20240929/20121052SNUpLM4gjt.png

這邊有兩個小重點
1.執行要在command模式啟用,在使用webdeveop\Scripts\activate.bat啟用
2.最前面就是你創建的目錄
3.其實就是要執行資料夾內的bat執行檔,所以你也可以直接cd 到webdeveop\Scripts內,使用activate.bat

如何確認已經進入環境了呢?
只要進入後看到command line前面有(環境名稱) 就代表成功進入了!!

你也可以使用pip list來看安裝列表會跟你在一般環境下的pip list有差別喔~
https://ithelp.ithome.com.tw/upload/images/20240929/20121052Smy2Hnq1L7.png

  1. 退出環境 deactivate

這邊就不放圖片了就是直接在command line模式打這行指令就會退出虛擬環境了。

只要前面沒有(環境名稱)就是退出了

Skill-2 錯誤處理 - try...except

定義

錯誤處理在coding skill中
也是相當重要的地位
舉例在後端工程師開發api中,會有許多的錯誤(網路、前端各式的資料格式錯誤、型態不符合、資料缺少...等)
都可以透過錯誤處理來丟出錯誤
來讓工程師或user看到錯誤在哪裡

編號 方法 功能描述 使用場景
1 tryexcept 捕獲和處理在 try 區塊中發生的異常,避免程序崩潰。 處理可能引發異常的代碼段,如文件操作或用戶輸入。
2 多個 except 可以為不同類型的異常定義多個 except 區塊,以便針對不同的錯誤進行特定處理。 當需要針對不同錯誤類型執行不同操作時。
3 else 區塊 try 區塊成功執行且沒有引發異常時執行的代碼。 當需要在沒有錯誤的情況下執行額外代碼時。
4 finally 區塊 無論是否發生異常,始終執行的代碼,通常用於清理資源,如關閉文件或釋放網絡連接。 確保資源得到釋放,即使發生異常也不例外。
5 自定義異常 通過創建自定義異常類來擴展標準異常,提供更具體的錯誤信息和處理方式。 當需要捕獲特定業務邏輯中的錯誤時。
6 使用 raise 主動引發異常,可以用於檢查條件並在不滿足條件時引發錯誤。 當需要強制執行某些條件時,例如參數驗證。

範例

1.基本的 try-except:

在前面輸入的程式碼中,我們可以增加try跟except

try:
    x = int(input("請輸入一個數字: "))
except ValueError:
    print("無效的輸入!請輸入有效的整數。")

1.當程式碼進到try區域的時候會嘗試執行操作,一旦有錯誤會進入到except中
2.如果沒有錯誤就會跳過except處理
3.except 可以定義各種錯誤
4.finally 可已讓程式碼無論是否盡到錯誤都會執行的區段

2.多個 except:

try:
    with open("file.txt") as f:
        content = f.read()
        num = int(content)
except FileNotFoundError:
    print("找不到文件!")
except ValueError:
    print("無法將內容轉換為整數!")

3.使用 else 和 finally:

try:
    result = 10 / 2
except ZeroDivisionError:
    print("不能除以零!")
else:
    print(f"結果是: {result}")
finally:
    print("這段代碼總是會被執行。")

tips - 這邊也可以直接把reslut寫在try裡,但是透過else可以讓程式碼更具有結構以及可讀性喔!!

4.自定義異常:

class MyCustomError(Exception):
    pass

def my_function():
    raise MyCustomError("這是一個自定義錯誤!")

try:
    my_function()
except MyCustomError as e:
    print(e)

可以使用前面學到的class來定義錯誤訊息,尤其是在設計API時可以給前段許多自定義的錯誤,
讓前端工程師更好判斷錯誤在哪要呈現什麼頁面喔

Skill-3 Log紀錄 - 使用logging模組

定義

在 Python 中,常用的日誌紀錄方式主要是使用內建的 logging 模組。這個模組提供了一種靈活且強大的方法來記錄程式運行時的各種信息。

編號 指令/功能 說明
1 import logging 引入 logging 模組以開始使用日誌功能。
2 logging.basicConfig() 設定日誌的基本配置,包括日誌級別、格式、輸出位置等。
3 logging.debug(message) 記錄 DEBUG 級別的日誌,通常用於開發過程中的詳細信息。
4 logging.info(message) 記錄 INFO 級別的日誌,通常用於一般的信息性消息。
5 logging.warning(message) 記錄 WARNING 級別的日誌,用於警告信息,表示可能出現問題。
6 logging.error(message) 記錄 ERROR 級別的日誌,用於錯誤信息,表示程式出現錯誤。
7 logging.critical(message) 記錄 CRITICAL 級別的日誌,用於嚴重錯誤,表示程式可能無法繼續運行。
8 logging.FileHandler(filename) 將日誌輸出到文件中,指定文件名。
9 logging.StreamHandler() 將日誌輸出到控制台(標準輸出)。
10 logger.addHandler(handler) 將處理器(Handler)添加到 Logger,以定義日誌的輸出方式。

示範

1. script模式

import logging

# 設定基本配置
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')

# 創建一個 FileHandler 並設置編碼為 utf-8
file_handler = logging.FileHandler('app.log', mode='a', encoding='utf-8')
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)

# 獲取根 logger 並添加 handler
logger = logging.getLogger()
logger.addHandler(file_handler)

# 記錄日誌
logger.info('這是一條信息級別的日誌')
logger.warning('這是一條警告級別的日誌')
logger.error('這是一條錯誤級別的日誌')

我們可以很簡單的操作script方式來記錄log模組
這個可以幫我們把script code中如果需要錯誤處理
可以搭配try...except 根loggin來把錯誤塞進log file

https://ithelp.ithome.com.tw/upload/images/20240929/20121052KLy6eHsOBG.png

2. web api log

from flask import Flask
import logging

app = Flask(__name__)

# 設定基本配置
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

@app.route('/')
def home():
    app.logger.info('訪問首頁')
    return 'Hello, World!'

@app.route('/error')
def error():
    app.logger.error('發生錯誤!')
    return 'Error occurred!', 500

if __name__ == '__main__':
    app.run()

雖然還沒交到,但我們也可以透過log模組紀錄api的錯誤訊息喔~!!

Skill-4 推導式(Comprehensions)

1.列表推導式(List Comprehensions)

定義
new_list = [expression for item in iterable if condition]

1.生成平方數列表

squares = [x**2 for x in range(10)]  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

2.過濾長度大於3的字符串並轉換為大寫

names = ['Bob', 'Tom', 'alice', 'Jerry', 'Wendy', 'Smith']
filtered_names = [name.upper() for name in names if len(name) > 3]  # ['ALICE', 'JERRY', 'WENDY', 'SMITH']

字典推導式(Dictionary Comprehensions)

定義
new_dict = {key_expression: value_expression for item in iterable if condition}

將列表轉換為字典,鍵為索引,值為元素:

names = ['A', 'B', 'C']
name_dict = {i: name for i, name in enumerate(names)}  # {0: 'A', 1: 'B', 2: 'C'}
優點 缺點
簡潔性:可以用一行代碼表達複雜的迭代和過濾操作,讓代碼更易讀。 學習成本:對初學者來說,推導式的語法可能較為陌生,需要時間學習。
可讀性:清晰地表達列表生成邏輯,避免多行代碼的冗長。 可讀性雙刃劍:過於複雜的推導式可能使代碼難以理解。
效率:通常比傳統的循環和條件判斷更快,因為在解釋器級別進行優化。 調試困難:當邏輯較為複雜時,調試可能變得困難,因為所有操作都壓縮在一行中。
靈活性:支持嵌套使用,可以生成複雜的數據結構,如二維列表、字典列表等。

Skill-5 效能運算-迴圈及向量比較

比較

1.較差的運算法

import time

# 效能差的版本
def square_numbers_loop(numbers):
    result = []
    for number in numbers:
        result.append(number ** 2)
    return result

# 測試
numbers = list(range(1000000))
start_time = time.time()
squared_numbers = square_numbers_loop(numbers)
end_time = time.time()

print("Using loop took:", end_time - start_time, "seconds")

2. 叫好的寫法(使用向量寫法)

import numpy as np

# 效能好的版本
def square_numbers_numpy(numbers):
    array = np.array(numbers)
    return array ** 2

# 測試
numbers = np.arange(1000000)
start_time = time.time()
squared_numbers = square_numbers_numpy(numbers)
end_time = time.time()

print("Using NumPy took:", end_time - start_time, "seconds")

python效能演算法比較網站

大家可以直接點這網址操作
https://perfpy.com/800

https://ithelp.ithome.com.tw/upload/images/20240929/201210525tuPwGn188.png

這邊想強調的是,在演算法面試或考試中,硬幹的迴圈處理大多時候會比使用數學公式處理還差喔!!
這也是為什麼,很多人說高階工程師需要一定的數學基礎~

總結

今天學會了5種技巧是對python程式設計師提升技能的小技巧
下周開始就會開始實作專案瞜~大家準備好了嗎?
/images/emoticon/emoticon01.gif


上一篇
[Day13] 第二週 - 進階工程師的開端 - 物件導向之三大特性
下一篇
[Day15] Python專案實踐周,學習心態的內外武功!? 跟學習目標(六大應用場景)
系列文
從概念到應用:Python實戰開發學習之旅31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言